#pragma once

#include <memory>

#include "INode.h"
#include "INodeFactory.h"

struct ApplyOnce
{
    template<class Processor>
    inline static bool Apply(std::auto_ptr<INode> & pNode, const Processor & processor)
    {
        return processor.process(pNode);
    }
};

struct ApplyUntilUnchanged
{
    template<class Processor>
    inline static bool Apply(std::auto_ptr<INode> & pNode, const Processor & processor)
    {
        bool bRes = false;
        while(processor.process(pNode))
            bRes = true;
            
        return bRes;
    }
};


template<class ApplyPolicy, class Processor>
bool Traverse(std::auto_ptr<INode> & pNode, const Processor & processor)
{
    bool bProcessed = ApplyPolicy::Apply(pNode, processor);

    // Process children
    size_t iChildrenCount = pNode->getChildrenCount();
    for(size_t i=0; i<iChildrenCount; ++i)
    {
        std::auto_ptr<INode> pChild(pNode->replaceChild(i, NULL));
        bProcessed |= Traverse<ApplyPolicy, Processor>(pChild, processor);
        pNode->replaceChild(i, pChild.release());
    }

    return bProcessed;
}





